/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.common.dataset.support.jxl;

import com.google.common.collect.Lists;
import jxl.*;
import org.vacoor.nothing.common.dataset.RecordConsumer;
import org.vacoor.nothing.common.dataset.support.SimpleRecord;
import org.vacoor.nothing.common.util.Throwables;

import java.io.InputStream;
import java.util.*;

/**
 * <p>
 * 一个简单的Excel工具类,
 * 用于解析简单的文本excel
 * 图片,字体等请参考jexcel api <br>
 * <p/>
 * http://www.andykhan.com/jexcelapi/<br>
 * http://sourceforge.net/projects/jexcelapi/
 * </p>
 *
 * @author vacoor
 */
public class JxlReader {
    private static final int PROCESS_ALL = -1;

    private final RecordConsumer consumer;

    public static JxlReader use(RecordConsumer consumer) {
        return new JxlReader(consumer);
    }

    private JxlReader(RecordConsumer consumer) {
        this.consumer = consumer;
    }

    /*
     * 处理给定 excel 流
     */
    public void read(InputStream in) {
        read(in, PROCESS_ALL);
    }

    /**
     * 处理给定 excel 的给定 sheet
     *
     * @param in
     * @param sheetIndex
     */
    public void read(InputStream in, int sheetIndex) {
        try {
            Workbook workbook = Workbook.getWorkbook(in);
            int numberOfSheets = workbook.getNumberOfSheets();

            if (sheetIndex > numberOfSheets - 1) {
                // TODO throw exception
                return;
            }

            sheetIndex = sheetIndex > -1 ? sheetIndex : PROCESS_ALL;

            if (PROCESS_ALL == sheetIndex) {
                for (int i = 0; i < numberOfSheets; i++) {
                    processSheet(workbook.getSheet(i));
                }
            } else {
                processSheet(workbook.getSheet(sheetIndex));
            }
        } catch (Exception e) {
            throw Throwables.unchecked(e);
        }
    }

    /**
     * 处理单个sheet
     *
     * @param sheet
     */
    private void processSheet(Sheet sheet) {
        // final String sheetName = sheet.getName();
        final int rows = sheet.getRows();
        final int columns = sheet.getColumns();

        // 遍历所有行
        for (int row = 0; row < rows; row++) {
            // 这里按照相同宽度和高度处理
            List<Object> rowData = Lists.newLinkedList();

            if (sheet.getRow(row).length < 1) {
                // 跳过空行
                continue;
            }

            // 遍历所有列
            for (int c = 0; c < columns; c++) {
                Cell cell = sheet.getCell(c, row);

                CellType type = cell.getType();

                if (CellType.EMPTY == type) {
                    rowData.add(null);
                } else if (CellType.BOOLEAN_FORMULA == type || CellType.BOOLEAN == type) {
                    BooleanCell bool = (BooleanCell) cell;
                    rowData.add(bool.getValue());
                } else if (CellType.LABEL == type || CellType.STRING_FORMULA == type) {
                    LabelCell label = (LabelCell) cell;
                    rowData.add(label.getString());
                } else if (type == CellType.NUMBER || type == CellType.NUMBER_FORMULA) {
                    NumberCell number = (NumberCell) cell;
                    rowData.add(number.getValue());
                } else if (type == CellType.DATE || type == CellType.DATE_FORMULA) {
                    DateCell date = (DateCell) cell;
                    // 时区为 GMT, Excel 使用GMT时区, Java 会使用默认时区, 这里不做处理了, 直接不允许使用时间
                        /*
                        if (date.isTime() && !TimeZone.getDefault().hasSameRules(TimeZone.getTimeZone("GMT"))) {
                            throw new IllegalStateException("Excel GMT 时区 与 当前默认时区不一致");
                        }
                        rowDatas.add(date.getDate());
                        */
                    Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
                    calendar.setTime(date.getDate());
                    calendar.add(Calendar.MILLISECOND, -TimeZone.getDefault().getRawOffset());

                    rowData.add(calendar.getTime());
                    /*
                    } else if (type == CellType.ERROR || type == CellType.FORMULA_ERROR) {
                        // ErrorFormulaCell error = (ErrorFormulaCell) cell;
                        ErrorCell error = (ErrorCell) cell;
                        System.out.println(error.getContents());
                    }
                    */
                } else {
                    rowData.add(cell.getContents());
                }
            }

            if (consumer != null) {
                consumer.onRecord(new SimpleRecord(row, Collections.unmodifiableList(rowData)));
            }
        }
    }
}
